package mop.controller;

import java.sql.Timestamp;
import java.util.Comparator;
import java.util.List;

import mop.exception.IllegalIdException;
import mop.exception.IllegalReservationException;
import mop.exception.IllegalReservationScheduleException;
import mop.exception.UnavailableResourceException;
import mop.model.DataBase;
import mop.model.World;
import mop.model.resource.ReservationInterface;
import mop.model.resource.Resource;
import mop.model.resource.ResourceInterface;
import mop.model.resource.filter.ReservationStartFilter;
import mop.model.task.Task;
import mop.model.task.TaskInterface;
import mop.model.task.filter.StateFilter;
import mop.util.filter.Filter;
import mop.util.sort.MergeSort;
import mop.util.sort.Sort;

/**
 * MakeResourceReservationController
 * 
 * Use case controller for the making of new resource reservations. 
 * (use case 10)
 * 
 * @author	MOP Team 7
 */
public class MakeResourceReservationController extends UseCaseController
{

	/**
	 * Creates a MakeResourceReservationController.
	 * @see UseCaseController#UseCaseController(World)
	 */
	public MakeResourceReservationController(World world)
	{
		super(world);
	}
	
	/**
	 * Returns a list of all resources as interfaces.
	 * @see super#getAllResources()
	 */
	public List<ResourceInterface> getResourceList()
	{
		return super.getAllResources();
	}

        /**
	 * Returns a list of unfinished tasks belonging to the current user.
	 * @see list of unfinished tasks from user
	 */
	public List<TaskInterface> getUnfinishedTasks()
	{
		Filter<TaskInterface> filter = new StateFilter("Unfinished");
		return filter.filter(super.getUserTasks());
	}
	
	/**
	 * Get a list of reservations for given resource
	 * 
	 * @param resourceid	Resource identifier
	 * @return List of reservations for now and future, sorted according to start time
	 * @throws IllegalIdException 	Resource is not found
	 * 	| @see DataBase#find(String)
	 */
	public List<ReservationInterface> getReservations(String resourceid) throws IllegalIdException{
		Filter<ReservationInterface> filter = new ReservationStartFilter((Timestamp) World.getTime());
		Sort<ReservationInterface> sorter = new MergeSort<ReservationInterface>();
		List<ReservationInterface> list = filter.filter(getWorld().getResourceDataBase().find(resourceid).getReservationsList());
		sorter.sort(list, new Comparator<ReservationInterface>(){
						/**
						 * @see Comparator#compare(Object,Object)
						 * First start time first
						 */
						@Override
						public int compare(ReservationInterface t1, ReservationInterface t2) {
							if(t1.getStart().getTime() < t2.getStart().getTime())
								return -1;
							else if(t1.getStart().getTime() == t2.getStart().getTime())
								return 0;
							else
								return 1;
						}
					});
		return list;
	}
	
	/**
	 * Return
	 */
	
	/**
	 * Makes a reservation for the given resource and the given time period.
	 * 
	 * @param	taskid		Identifier of task to make reservation for
	 * @param 	resourceid	Identifier of resource to reservate
	 * @param 	start		Start timestamp of reservation
	 * @param	duration	Duration period of reservation
	 * 
	 * @throws 	UnavailableResourceException 
	 * 			@see {@link Resource#addReservation(Task, Timestamp, Timestamp)}
	 * @throws 	IllegalReservationException
	 * 			@see {@link Task#addReservation(mop.model.resource.Reservation)}
	 * @throws	IllegalIdException 
	 * 			@see DataBase#find(String)
	 * @throws IllegalReservationScheduleException 
	 * 			@see {@link Task#addReservation(mop.model.resource.Reservation)}
	 */
	public void makeReservation(String taskid, String resourceid, Timestamp start, Timestamp duration) 
		throws IllegalReservationException, UnavailableResourceException, IllegalIdException, IllegalReservationScheduleException
	{
		Resource r = getWorld().getResourceDataBase().find(resourceid);
		Task t = getWorld().findTask(taskid);
		
		r.addReservation(t, start, duration);
	}
	
	
	/***************************************************************************
	 * 								Visit
	 ***************************************************************************/
	
	/**
	 * Make a CallBack to the visitor
	 * @param v the visitor
	 */
	public void accept(ControllerVisitor v)
	{
		v.visit(this);
	}
	
	/***************************************************************************
	 * 								Acl
	 ***************************************************************************/
	
	@Override
	public String getAssetId() {
		return "MakeReservation";
	}

}